module klang.json.编译.json编译_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import ··节点_ = klang.编译.语法节点.节点_;
import ··诊断_ = klang.编译.诊断.诊断_;
import klang.编译.编译.编译_: 编译器_;
import klang.编译.语法节点.节点_: 节点_, 令牌_, 源文件_;
import klang.编译.类型.枚举值.枚举值_: SK, 字符_, 令牌标志_;
import klang.编译.类型.类型_: 前端编译器接口_, 编译器基类_;
import 编译数字 = 编译数字.编译;
import klang.编译.诊断集.诊断集_: 诊断集_;
import klang.编译.核心.核心_: 整数_;
import klang.json.语法节点.json节点_: JSK, Json令牌语法_, 创建节点, Json源文件_, Json令牌_, 表达式_, Json节点_, 字面量类_, 文本字面量_, 数字字面量_, 小数字字面量_, 一元前缀表达式_, 数组字面量_, 对象字面量_, 属性赋值表达式_, 表达式语句_;
编译器_ 编译器 = ··null!(编译器_);
Json源文件_ 当前源文件;
class 前端编译器_ : 前端编译器接口_ {
    编译器_ 编译器;
    this() { }
    this(编译器基类_ 编译) {
        this.编译器 = (cast(编译器_)(编译));
        .编译器 = this.编译器;
    }
    源文件_ 编译源文件() {
        .编译json源文件();
        return .当前源文件;
    }
    void 清理() {
        编译器.清理();
    }
}
void 编译json源文件() {
    编译器.下个令牌();
    long 文件开始 = 编译器.获取节点开始();
    if (编译器.令牌() == SK.文件结尾) {
        .当前源文件 = (cast(Json源文件_)(编译器.当前源文件));
        当前源文件.语句组 = 编译器.f·创建节点数组!(节点_)([], 0);
        当前源文件.文件结尾令牌 = 编译器.f·编译令牌节点!(令牌_!(SK))();
        return;
    }
    else {
        表达式语句_ 语句 = 创建节点!(表达式语句_)(JSK.表达式语句);
        switch (编译器.令牌()) {
            case SK.左方括号: {
                语句.表达式 = .编译数组字面量();
                break;
            }
            case SK.减号: {
                if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() == SK.数字字面量 && 编译器.下个令牌() != SK.冒号; })) {
                    long 减号开始 = 编译器.获取节点开始();
                    编译器.下个令牌();
                    字面量类_ 表达式 = .编译数字字面量();
                    一元前缀表达式_ 节点 = 创建节点!(一元前缀表达式_)(JSK.一元前缀表达式);
                    节点.表达式 = 表达式;
                    节点.运算符 = SK.减号;
                    语句.表达式 = 编译器.f·完成节点!(一元前缀表达式_)(节点, 减号开始);
                }
                else {
                    编译器.下个令牌();
                    语句.表达式 = .编译对象字面量();
                }
                break;
            }
            case SK.标识符: {
                dstring id = 编译器.获取令牌值();
                if (id == "true"d || id == "真"d) {
                    语句.表达式 = .编译Json令牌!(JSK)(JSK.真_, 文件开始);
                }
                else if (id == "flase"d || id == "假"d) {
                    语句.表达式 = .编译Json令牌!(JSK)(JSK.假_, 文件开始);
                }
                else if (id == "null"d || id == "空值"d) {
                    语句.表达式 = .编译Json令牌!(JSK)(JSK.空值_, 文件开始);
                }
                break;
            }
            case SK.文本字面量: {
                if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() != SK.冒号; })) {
                    语句.表达式 = .编译文本字面量();
                    break;
                }
            }
            case SK.数字字面量: {
                if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() != SK.冒号; })) {
                    语句.表达式 = .编译文本字面量();
                    break;
                }
            }
            // 贯穿
            default: {
                语句.表达式 = .编译对象字面量();
                break;
            }
        }
        编译器.f·完成节点!(表达式语句_)(语句, 文件开始);
        .当前源文件 = (cast(Json源文件_)(编译器.当前源文件));
        当前源文件.语句组 = 编译器.f·创建节点数组!(节点_)([语句], 文件开始);
        当前源文件.文件结尾令牌 = 编译器.f·编译令牌节点!(令牌_!(SK))();
    }
}
Json令牌_!(T) 编译Json令牌(T)(JSK tsk, long 令牌开始) {
    编译器.下个令牌();
    return 编译器.f·完成节点!(Json令牌_!(T))(创建节点!(Json令牌_!(T))(tsk), 令牌开始);
}
数组字面量_ 编译数组字面量() {
    long 字面量开始 = 编译器.获取节点开始();
    数组字面量_ 节点 = 创建节点!(数组字面量_)(JSK.数组字面量);
    if (!编译器.编译确定的(SK.左方括号)) {
        编译器.下个令牌();
    }
    long 数组开始 = 编译器.获取节点开始();
    Json节点_[] 数组 = [];
    while(编译器.令牌() != SK.右方括号) {
        if (编译器.令牌() == SK.逗号) {
            编译器.下个令牌();
            continue;
        }
        数组 = .追加!(Json节点_)(数组, .编译表达式());
    }
    节点.元素组 = 编译器.f·创建节点数组!(Json节点_)(数组, 数组开始);
    if (!编译器.编译确定的(SK.右方括号)) {
        编译器.下个令牌();
    }
    数组字面量_ 结果 = 编译器.f·完成节点!(数组字面量_)(节点, 字面量开始);
    return 结果;
}
对象字面量_ 编译对象字面量() {
    long 字面量开始 = 编译器.获取节点开始();
    对象字面量_ 节点 = 创建节点!(对象字面量_)(JSK.对象字面量);
    if (!编译器.编译确定的(SK.左大括号)) {
        编译器.下个令牌();
    }
    long 对象开始 = 编译器.获取节点开始();
    Json节点_[] 数组 = [];
    while(编译器.令牌() != SK.右大括号) {
        if (编译器.令牌() == SK.逗号) {
            编译器.下个令牌();
            continue;
        }
        数组 = .追加!(Json节点_)(数组, .编译表达式());
    }
    节点.元素组 = 编译器.f·创建节点数组!(Json节点_)(数组, 对象开始);
    if (!编译器.编译确定的(SK.右大括号)) {
        编译器.下个令牌();
    }
    对象字面量_ 结果 = 编译器.f·完成节点!(对象字面量_)(节点, 字面量开始);
    return 结果;
}
Json节点_ 编译表达式() {
    long 表达式开始 = 编译器.获取节点开始();
    switch (编译器.令牌()) {
        case SK.左方括号: {
            return .编译数组字面量();
        }
        case SK.左大括号: {
            return .编译对象字面量();
        }
        case SK.减号: {
            if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() == SK.数字字面量 && 编译器.下个令牌() != SK.冒号; })) {
                long 减号开始 = 编译器.获取节点开始();
                编译器.下个令牌();
                字面量类_ 表达式 = .编译数字字面量();
                一元前缀表达式_ 节点 = 创建节点!(一元前缀表达式_)(JSK.一元前缀表达式);
                节点.表达式 = 表达式;
                节点.运算符 = SK.减号;
                return 编译器.f·完成节点!(一元前缀表达式_)(节点, 减号开始);
            }
            else {
                编译器.下个令牌();
                return .编译对象字面量();
            }
        }
        case SK.标识符: {
            dstring id = 编译器.获取令牌值();
            if (id == "true"d || id == "真"d) {
                return .编译Json令牌!(JSK)(JSK.真_, 表达式开始);
            }
            else if (id == "flase"d || id == "假"d) {
                return .编译Json令牌!(JSK)(JSK.假_, 表达式开始);
            }
            else if (id == "null"d || id == "空值"d) {
                return .编译Json令牌!(JSK)(JSK.空值_, 表达式开始);
            }
        }
        case SK.文本字面量: {
            if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() != SK.冒号; })) {
                return .编译文本字面量();
            }
        }
        case SK.数字字面量: {
            if (编译器.f·向前看!(bool)(() { return 编译器.下个令牌() != SK.冒号; })) {
                return .编译数字字面量();
            }
        }
        default: {
            return .编译属性赋值表达式();
        }
    }
    throw new Throwable(·to!(string)(("不支持"d)));
}
属性赋值表达式_ 编译属性赋值表达式() {
    long 属性开始 = 编译器.获取节点开始();
    dstring 名称 = 编译器.获取令牌值();
    编译器.下个令牌();
    if (!编译器.编译确定的(SK.冒号)) {
        编译器.下个令牌();
    }
    Json节点_ 表达式 = .编译表达式();
    属性赋值表达式_ 节点 = 创建节点!(属性赋值表达式_)(JSK.属性赋值表达式);
    节点.表达式 = 表达式;
    节点.名称 = 名称;
    return 编译器.f·完成节点!(属性赋值表达式_)(节点, 属性开始, 表达式.结束);
}
字面量类_ 编译数字字面量() {
    long 数字开始 = 编译器.获取节点开始();
    if ((编译器.获取令牌标志() & 令牌标志_.是小数_) != 0) {
        dstring 值文本 = 编译器.获取令牌值();
        double 数字值 = 编译数字.编译!(double)(值文本, 10);
        小数字字面量_ 节点 = 创建节点!(小数字字面量_)(JSK.小数字字面量);
        节点.内容 = 值文本;
        节点.值 = 数字值;
        编译器.下个令牌();
        return 编译器.f·完成节点!(小数字字面量_)(节点, 数字开始);
    }
    dstring _0 = 编译器.获取令牌值();
    if (_0 == "0"d) {
        return 编译器.f·尝试编译!(数字字面量_)(cast(数字字面量_ delegate())(·fd(&.可能是是十六进制或八进制或二进制数字)));
    }
    dstring 值文本 = 编译器.获取令牌值();
    long 数字值 = 编译数字.编译!(long)(值文本, 10);
    数字字面量_ 节点 = 创建节点!(数字字面量_)(JSK.数字字面量);
    节点.内容 = 值文本;
    节点.值 = 数字值;
    编译器.下个令牌();
    return 编译器.f·完成节点!(数字字面量_)(节点, 数字开始);
}
字面量类_ 编译文本字面量() {
    long 文本开始 = 编译器.获取节点开始();
    dstring 内容 = 编译器.获取令牌值();
    文本字面量_ 节点 = 创建节点!(文本字面量_)(JSK.文本字面量);
    节点.内容 = 内容;
    编译器.下个令牌();
    return 编译器.f·完成节点!(文本字面量_)(节点, 文本开始);
}
bool 前面有杂项() {
    return (编译器.获取令牌标志() & 令牌标志_.令牌前有杂项) != 0;
}
数字字面量_ 可能是是十六进制或八进制或二进制数字() {
    long 可能开始 = 编译器.获取节点开始();
    编译器.下个令牌();
    if (!.前面有杂项() && 编译器.令牌() == SK.标识符) {
        dstring 内容 = 编译器.获取令牌值();
        if (内容.length >= 2) {
            immutable(dchar) ch = 内容[0];
            内容 = 内容[1 .. $];
            if ((ch == 字符_.x || ch == 字符_.X) && .文本是十六进制的(内容)) {
                数字字面量_ n = 创建节点!(数字字面量_)(JSK.数字字面量);
                n.内容 = "0x"d ~ 内容;
                n.值 = 编译数字.编译!(long)(内容, 16);
                编译器.下个令牌();
                数字字面量_ 结果 = 编译器.f·完成节点!(数字字面量_)(n, 可能开始);
                return 结果;
            }
            else if (ch == 字符_.b || ch == 字符_.B) {
                dstring 新内容 = ""d;
                bool 成功 = .文本是二进制的(内容, 新内容);
                if (成功) {
                    数字字面量_ n = 创建节点!(数字字面量_)(JSK.数字字面量);
                    n.内容 = "0b"d ~ 内容;
                    n.值 = 编译数字.编译!(long)(新内容, 2u);
                    编译器.下个令牌();
                    数字字面量_ 结果 = 编译器.f·完成节点!(数字字面量_)(n, 可能开始);
                    return 结果;
                }
            }
            else if (ch == 字符_.o || ch == 字符_.O) {
                dstring 新内容 = ""d;
                bool 成功 = .文本是八进制的(内容, 新内容);
                if (成功) {
                    数字字面量_ n = 创建节点!(数字字面量_)(JSK.数字字面量);
                    n.内容 = "0o"d ~ 内容;
                    n.值 = 编译数字.编译!(long)(新内容, 8);
                    编译器.下个令牌();
                    数字字面量_ 结果 = 编译器.f·完成节点!(数字字面量_)(n, 可能开始);
                    return 结果;
                }
            }
        }
        数字字面量_ n = 创建节点!(数字字面量_)(JSK.数字字面量);
        n.内容 = 内容;
        n.值 = 0;
        编译器.下个令牌();
        编译器.编译错误在(可能开始, 编译器.获取节点开始(), 诊断集_.Unexpected_token);
        数字字面量_ 结果 = 编译器.f·完成节点!(数字字面量_)(n, 可能开始);
        return 结果;
    }
    else {
        数字字面量_ n = 创建节点!(数字字面量_)(JSK.数字字面量);
        n.内容 = "0"d;
        n.值 = 0;
        数字字面量_ 结果 = 编译器.f·完成节点!(数字字面量_)(n, 可能开始);
        return 结果;
    }
}
bool 文本是十六进制的(dstring 内容) {
    {
        for (int i = 0; i < 内容.length; ++i) {
            immutable(dchar) ch = 内容[i];
            if (!(ch >= 字符_.数_0 && ch <= 字符_.数_9 || ch >= 字符_.a && ch <= 字符_.f || ch >= 字符_.A && ch <= 字符_.F)) {
                return false;
            }
        }
    }
    return true;
}
bool 文本是八进制的(dstring 内容, ref dstring 新内容) {
    dstring 值内容 = [];
    {
        for (int i = 0; i < 内容.length; ++i) {
            immutable(dchar) ch = 内容[i];
            if (!((ch >= 字符_.数_0 && ch <= 字符_.数_7) || ch == 字符_.下划线)) {
                新内容 = 内容;
                return false;
            }
            if (ch != 字符_.下划线) {
                值内容 = .追加!(immutable(dchar))(值内容, ch);
            }
        }
    }
    新内容 = ·to!(dstring)(值内容);
    return true;
}
bool 文本是二进制的(dstring 内容, ref dstring 新内容) {
    dstring 值内容 = [];
    {
        for (int i = 0; i < 内容.length; ++i) {
            immutable(dchar) ch = 内容[i];
            if (!((ch >= 字符_.数_0 && ch <= 字符_.数_1) || ch == 字符_.下划线)) {
                新内容 = 内容;
                return false;
            }
            if (ch != 字符_.下划线) {
                值内容 = .追加!(immutable(dchar))(值内容, ch);
            }
        }
    }
    新内容 = ·to!(dstring)(值内容);
    return true;
}
